home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 201-225 / disk_223 / iff2sun / iff2sun.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  11KB  |  479 lines

  1. /*
  2. **      This Program created (under tremendous pressure) by Steve Berry
  3. **      with help and modifications by Mark Thompson and others.
  4. **
  5. **      I hope you guys keep it clean. (If you don't, let me know :-)
  6. **
  7. **      Status: PD all the way.
  8. **
  9. **      Please read the file named DOC, that came with this distribution for
  10. **      information on how to use iff2sun.
  11. **
  12. **    Limitations:
  13. **          I have only tested this on DPaintII images, it is
  14. **        very possible that it might break with other formats.
  15. **        Unlikely, but possible :*)
  16. **
  17. **    CREDITS:
  18. **            Mark Thompson
  19. **            Steve (Raz) Berry
  20. **
  21. **    Contacts:
  22. **                Steve Berry ...sun!kilowatt!raz or 
  23. **                                             raz%kilowatt.EBay@sun.com
  24. **                                          BIX: razberry
  25. **                              Mark Thompson  ...decvax!savax!thompson
  26. **
  27. **      Revision History:
  28. **
  29. **      10/31/88 First release, does only simple conversion and no color.
  30. **
  31. **      12/88    Re-released with color support. Unfortunately few if any
  32. **               one saw this release (it got lost on the way to the moderator)
  33. **               (This is Mark's claim to fame)
  34. **
  35. **      4/26/89  Added Extra-half-bright support, also looking for the
  36. **               best way to convert HAM (4096) to 8 bit (256) format.
  37. **
  38. **    5/26/89     Added HAM mode conversion (with convert) and fixed an iff
  39. **         parsing bug (parse()), and added new argument parsing supplied
  40. **         by Tony Schene. The original convert.c was supplied by
  41. **         Tony Kennedy as well as the bug report on DPaintIII images.
  42. */
  43.  
  44. #include <sys/types.h>
  45. #include <stdio.h>
  46. #include <rasterfile.h>
  47.  
  48. #define HAM 0x800       /* Amiga Viewmodes */
  49. #define HALF 0x80
  50. #define HIRES 0x8000
  51. #define LACE 0x4
  52. #define TRUE 1
  53. #define FALSE 0
  54.  
  55. /* Stupic C needs to be told about functions used before they
  56.    are defined */
  57.  
  58. unsigned char RGBtoLuma();
  59. long parse();
  60.  
  61. /* Some variables and arrays */
  62.  
  63. u_char    rmap[128],rhmap[128];
  64. u_char    gmap[128],ghmap[128];
  65. u_char    bmap[128],bhmap[128];
  66. u_char currentcolor[3];
  67. u_char scanline[1024][6][128]; /* vert, planes, width (bytes) */
  68.  
  69. long width, hieght, planes, hammode, numcolors;
  70. long temp, compress, i, j, k, l;
  71. int colorpic=FALSE, halfb = FALSE, pixelrep = FALSE;
  72. char *Usage = "Usage: %s [ -chp ] [ infile ] [ outfile ]\n";
  73.  
  74. main(argc,argv)
  75. int argc;
  76. char **argv;
  77. {
  78.     struct rasterfile header;
  79.     unsigned char clr;
  80.     long formsize, twidth, thieght;
  81.     static char chunk[5];
  82.     FILE *inh, *outh;
  83.     char    *progname= argv[0];
  84.     char c;
  85.     extern char *optarg;
  86.     extern int optind;
  87.         
  88.     chunk[4] = 0;
  89.         
  90.     inh = stdin;
  91.     outh = stdout;
  92.  
  93.     while ((c = getopt (argc, argv, "chp")) != -1)
  94.         switch (c) {
  95.         case 'c':
  96.             colorpic = TRUE;
  97.             fprintf(stderr,"Color output selected\n");
  98.             break;
  99.         case 'h':
  100.             halfb = TRUE;
  101.             fprintf(stderr,"Extra Half-bright selected\n");
  102.             break;
  103.         case 'p':
  104.             pixelrep = TRUE;
  105.             break;
  106.         default:
  107.             fprintf (stderr, Usage, argv[0]);
  108.             exit (1);
  109.           }
  110.     if (optind < argc)
  111.         inh = fopen(argv[optind],"r");
  112.     if (++optind < argc)
  113.         outh = fopen(argv[optind],"w");
  114.     if (++optind < argc) {
  115.         fprintf (stderr, Usage, argv[0]);
  116.         exit (1);
  117.     }
  118.         
  119.     if (inh == NULL){
  120.         perror(argv[1]);
  121.         exit(-10);
  122.     }        
  123.  
  124.     if (outh == NULL){
  125.         perror(argv[2]);
  126.         exit(-10);
  127.     }        
  128.  
  129.     /* Now comes the fun part... Reading the ILBM's */
  130.         
  131.     if (parse(inh,"FORM")) {
  132.         perror("I don't think that this is an IFF file");
  133.         exit(-10);
  134.     }
  135.  
  136.     fread(&formsize, 4, 1, inh);    /* length of the FORM */
  137.  
  138.     if (parse(inh,"ILBM")) {
  139.         perror("I don't think that this is an ILBM");
  140.         exit(-10);
  141.     }
  142.  
  143.     if (parse(inh,"BMHD")) { 
  144.         perror("Bad format for ILBM.");
  145.         exit(-10);
  146.     }
  147.  
  148.     cc(chunk);
  149.     fread(chunk, 4, 1, inh);    /* length of the BMHD */
  150.  
  151.     cc(chunk);
  152.     fread(chunk, 2, 1, inh);    /* width of bitmap */
  153.     width = *((short *)chunk);
  154.  
  155.     cc(chunk);
  156.     fread(chunk, 2, 1, inh);    /* Height of bitmap */
  157.     hieght = *((short *)chunk);
  158.  
  159.     fread(chunk, 4, 1, inh);    /* Don't want the orgins */
  160.  
  161.     cc(chunk);
  162.     fread(chunk, 1, 1, inh);    /* # of Planes */
  163.     planes = *((unsigned char *)chunk);
  164.  
  165.     fread(chunk, 1, 1, inh);    /* Ignore the Mask */
  166.  
  167.     cc(chunk);
  168.     fread(chunk, 1, 1, inh);    /* Compression? */
  169.  
  170.     compress = *((unsigned char *)chunk);
  171.  
  172.     fread(chunk, 1, 1, inh);    /* just a pad byte */
  173.  
  174. /***********************************************************************
  175. **    DpaintII does not use the CAMG chunk, so we will have to ignore
  176. **    it for now...
  177. ***********************************************************************/
  178.  
  179. /*    if (planes == 6) {
  180.         perror("Sorry, I can't do HAM or Halfbright.");
  181.         exit(0);
  182.     } */
  183.  
  184.     if (parse(inh,"CMAP")) {
  185.         perror("Bad format for ILBM, couldn't find Color Map.");
  186.     exit(-10);
  187.     } 
  188.  
  189.     cc(chunk);
  190.     fread(chunk, 4, 1, inh);    /* # of color registers */
  191.     numcolors = *((long *)chunk);
  192.         
  193.     for(i=0; i<64; i++) {
  194.       rmap[i]= i;
  195.       gmap[i]= i;
  196.       bmap[i]= i;
  197.     }
  198.  
  199.     numcolors = numcolors/3 ;
  200.     for (i=0;i<numcolors;i++){
  201.         fread(chunk, 3, 1, inh);
  202.         chunk[3] = 0; chunk[4] = 0; 
  203.         chunk[0] = (chunk[0] >> 4) & 0x0f;
  204.         chunk[2] = (chunk[2] >> 4) & 0x0f;
  205.         chunk[1] = (chunk[1] >> 4) & 0x0f;
  206.         if(colorpic==TRUE) {
  207.           rmap[i] = (chunk[0] << 4) | chunk[0];
  208.           gmap[i] = (chunk[1] << 4) | chunk[1];
  209.           bmap[i] = (chunk[2] << 4) | chunk[2];
  210.         } else {
  211.           rmap[i] = RGBtoLuma(chunk);
  212.           gmap[i] = RGBtoLuma(chunk);
  213.           bmap[i] = RGBtoLuma(chunk);
  214.         }
  215.         if (halfb == TRUE) {
  216.           rhmap[i] = rmap[i]>>1;
  217.           ghmap[i] = gmap[i]>>1;
  218.           bhmap[i] = bmap[i]>>1;
  219.         }
  220.     }
  221.  
  222.     if (numcolors == 2)    /* if a mono image, realign to long word */
  223.         fread(chunk,1,2,inh);
  224.  
  225.     if (parse(inh,"BODY")){
  226.         perror("No BODY data.");
  227.         exit(0);
  228.     }
  229.  
  230.     if ((planes == 6) && (halfb == TRUE) && (numcolors == 16)
  231.           || (planes != 6) && (halfb == TRUE)){
  232.       perror("You specified Half-Bright, but file is not in the correct format\n");
  233.       exit(0);
  234.     }
  235.  
  236.     if ((planes == 6) && (halfb != TRUE)) {
  237.       fprintf(stderr, "Ham mode... raw color output initiated.\n");
  238.       hammode = TRUE;
  239.     }
  240.  
  241.     fread(chunk, 4, 1, inh);    /* length of body */
  242.  
  243.     if (!hammode) {
  244.       header.ras_magic= 0x59a66a95;
  245.       if (pixelrep == FALSE)
  246.         header.ras_width= width;
  247.       else
  248.         header.ras_width= width * 2;
  249.       header.ras_height= hieght;
  250.       header.ras_depth= 8;
  251.       if (pixelrep == FALSE)
  252.         header.ras_length= width * hieght;
  253.       else
  254.         header.ras_length= width * 2 * hieght;
  255.       header.ras_type= RT_STANDARD;
  256.       header.ras_maptype= RMT_EQUAL_RGB;
  257.       header.ras_maplength= 3*256;
  258.  
  259. /* Write out the rasterfile header to the ouput */
  260.  
  261.       fwrite(&header, sizeof(header), 1, outh);
  262.  
  263. /* Write out the red colormap to the ouput */
  264.  
  265.  
  266.       if (fwrite(rmap, sizeof(rmap), 1, outh) == 0) {
  267.         perror(progname);
  268.         exit(1);
  269.       } 
  270.       if (halfb == TRUE) 
  271.         fwrite(rhmap, sizeof(rhmap), 1, outh);
  272.       else 
  273.         fwrite(rmap, sizeof(rmap), 1, outh);
  274.  
  275. /* Write out the green colormap to the ouput */
  276.     
  277.       if (fwrite(gmap, sizeof(gmap), 1, outh) == 0) {
  278.         perror(progname);
  279.         exit(1);
  280.       } 
  281.       if (halfb == TRUE) 
  282.         fwrite(ghmap, sizeof(ghmap), 1, outh);
  283.       else 
  284.         fwrite(gmap, sizeof(gmap), 1, outh);
  285.  
  286. /* Write out the blue colormap to the ouput */
  287.  
  288.       if (fwrite(bmap, sizeof(bmap), 1, outh) == 0) {
  289.         perror(progname);
  290.         exit(1);
  291.       } 
  292.       if (halfb == TRUE) 
  293.         fwrite(bhmap, sizeof(bhmap), 1, outh);
  294.       else 
  295.         fwrite(bmap, sizeof(bmap), 1, outh);
  296.     }
  297.     else {
  298.       twidth = width;
  299.       if (pixelrep) {
  300.         twidth = width * 2;
  301.       }
  302.       fwrite(&twidth, 4, 1, outh);
  303.       fwrite(&hieght, 4, 1, outh);
  304.     }
  305.  
  306. /* This part does all the work */
  307.  
  308. /* Either we uncompress the file, or we read it in... */
  309.  
  310.     if (compress == 1)
  311.       uncompress(planes, width, inh);
  312.     else 
  313.       for(k = 0;k<hieght;k++)
  314.         for(i = 0;i<planes;i++) {
  315.           for(j=0;j<width/8;j++){
  316.         cc(chunk);
  317.         if(feof(inh))
  318.           continue;
  319.         fread(chunk, 1, 1, inh);
  320.         scanline[k][i][j] = *((unsigned char *)chunk);
  321.           }
  322.         }
  323.  
  324. /* Here we take the data and output it (finally!) */
  325.  
  326.     currentcolor[0] = rmap[0];
  327.     currentcolor[1] = gmap[0];
  328.     currentcolor[2] = bmap[0];
  329.  
  330.     for(j = 0;j<hieght;j++){
  331.       for(i = 0;i<width/8;i++)
  332.         process_pixel(i,j,outh);
  333.     }
  334.     fclose(inh);
  335.     fclose(outh);
  336. } /* end of main */
  337.  
  338. /* The uncompression routine                     */
  339. /* Here we uncompress the data for the number of planes     */
  340. /* and store it in the global array scanline[][][]         */
  341. /* Credits: Leo (the great Caped one) was the originator of the */
  342. /* code I ripped this off from.                 */
  343.  
  344. uncompress(planes, width, inh)
  345. FILE *inh;
  346. long planes, width;
  347. {
  348.     long i,j,count,bytesperrow;
  349.     char len;
  350.     unsigned char byte;
  351.  
  352.     for(i=0;i<hieght;i++){
  353.         for(j=0;j<planes;j++){
  354.             count = 0;
  355.             bytesperrow = width / 8;
  356.             while(bytesperrow > 0){
  357.                 if ((len = getc(inh)) >= 0){
  358.                     bytesperrow -= ++len;
  359.                     fread(&scanline[i][j][count],len,1,inh);
  360.                     count += len;
  361.                 } else if (len == -128)
  362.                     ;
  363.                 else if (len < 0){
  364.                     len = -len + 1;
  365.                     bytesperrow -= len;
  366.                     byte = getc(inh);
  367.                     while(--len >= 0)
  368.                         scanline[i][j][count++] = byte;
  369.                 }
  370.             }
  371.             if(bytesperrow)
  372.                 perror("Compression is messed.");
  373.         }
  374.         
  375.     }
  376. }
  377.  
  378.  
  379. /* RGBtoLuma converts the colortable from the Amiga to Luminance information */
  380. /* This routine was written by Mark Thompson                      */
  381.  
  382. unsigned char RGBtoLuma(color)
  383. unsigned char *color;
  384. {
  385.     unsigned char r, g, b;
  386.     unsigned char grey;
  387.     float fgrey;
  388.  
  389.     r = (color[0] << 4) + color[0];
  390.     g = (color[1] << 4) + color[1];
  391.     b = (color[2] << 4) + color[2];
  392.     fgrey = 0.3 * r + 0.59 * g + 0.11 * b + 0.5;
  393.     grey = fgrey;
  394.     return grey;
  395. }
  396.  
  397. /* Process the byte for the scanline         */
  398. /* Can you say shift 3 times fast?         */
  399.  
  400. process_pixel(byte,scan,outh)
  401. FILE *outh;
  402. unsigned char byte;
  403. long scan;
  404. {
  405.     long j, i, p, result = 0;
  406.     unsigned char temp;
  407.  
  408.     temp = 0; result = 0;
  409.     for(i=7;i>=0;i--){
  410.         for(p=0;p<planes;p++) 
  411.             result = ((((1 << i) & scanline[scan][p][byte])>>i)<<p) | result;
  412.         result = result & 0x3f;
  413.         temp = result;
  414.  
  415.         if (hammode) {
  416.           temp = (result & 0x30) >> 4;
  417.           switch (temp){
  418.           case 0x0:
  419.             temp = result & 0x0f;
  420.             currentcolor[2] = bmap[temp]<<4;
  421.             currentcolor[1] = gmap[temp]<<4; 
  422.             currentcolor[0] = rmap[temp]<<4;
  423.             break;
  424.           case 0x1:
  425.             result = result & 0x0f;
  426.             currentcolor[2] = result<<4;
  427.             break;
  428.           case 0x2:
  429.             result = result & 0x0f;
  430.             currentcolor[0] = result<<4;
  431.             break;
  432.           case 0x3:
  433.             result = result & 0x0f;
  434.             currentcolor[1] = result<<4;
  435.             break;
  436.           }
  437.  
  438.           fwrite(currentcolor, 1, 3, outh);
  439.           if (pixelrep == TRUE)
  440.             fwrite(currentcolor, 1, 3, outh);
  441.         }
  442.         else {
  443.           fwrite(&temp, 1, 1, outh);
  444.           if (pixelrep == TRUE)
  445.             fwrite(&temp, 1, 1, outh);
  446.         }
  447.         result = 0;
  448.     }
  449. }
  450.  
  451. /* look for a chunk in the file */
  452. long parse(inh, str)
  453. FILE *inh;
  454. char *str;
  455. {
  456.         static char chunk[5];
  457.         chunk[4] = 0;
  458.         while (1){
  459.       fread(chunk, 2, 1, inh);
  460.       if (strncmp(chunk,str,2) == 0){
  461.         fread(chunk, 2, 1, inh);
  462.         if (strncmp(chunk,&str[2],2) == 0)
  463.           return FALSE;
  464.       }
  465.       if(feof(inh) != 0)
  466.         return TRUE;
  467.         }
  468. }
  469.  
  470. /* Clear Chunk variable */
  471.  
  472. cc(chunk)
  473. char chunk[5];
  474. {
  475.     register int i;
  476.     for(i=0;i<5;i++)
  477.         chunk[i] = 0;
  478. }
  479.